package com.hmdp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.dto.LoginFormDTO;
import com.hmdp.dto.Result;
import com.hmdp.dto.UserDTO;
import com.hmdp.entity.User;
import com.hmdp.mapper.UserMapper;
import com.hmdp.service.IUserService;
import com.hmdp.utils.RegexUtils;
import com.hmdp.utils.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;

import static com.hmdp.utils.RedisConstants.LOGIN_CODE_KEY;
import static com.hmdp.utils.SystemConstants.USER_NICK_NAME_PREFIX;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 发送验证码
     * @param phone
     * @param session
     * @return
     */
    @Override
    public Result sendCode(String phone, HttpSession session) {
        // 1、首先校验手机号是否合法
        boolean isInValid = RegexUtils.isPhoneInvalid(phone);
        // 2、生成验证码或返回错误信息
        if(isInValid){
            return Result.fail("手机号非法！");
        }
        String code = RandomUtil.randomNumbers(6);

        // 3、将验证码保存到session中
        session.setAttribute("code",code);
        // 4、发送验证码
        log.info("收到验证码，验证码为：{}",code);
        return Result.ok();
    }

    /**
     * 用户登录
     * @param loginForm
     * @param session
     * @return
     */
    @Override
    public Result login(LoginFormDTO loginForm, HttpSession session) {
        String code = loginForm.getCode();
        String phone = loginForm.getPhone();
        // 1、首先校验验证码是否正确
        String cacheCode = (String)session.getAttribute("code");
        if(!code.equals(cacheCode)){
            return Result.fail("验证码错误!");
        }
        // 2、校验手机号是否合法
        if(RegexUtils.isPhoneInvalid(phone)){
            return Result.fail("手机号格式不合法!");
        }
        // 3、用户是否存在
        User user = lambdaQuery().eq(User::getPhone, phone).one();
        if(user == null){
            // 创建新的用户并保存到数据库中
             user = createNewUser(phone);
        }
        // 4、保存用户信息到session中
        session.setAttribute("user", BeanUtil.copyProperties(user, UserDTO.class));
        return Result.ok();
    }

    /**
     * 未注册用户直接创建一个新用户
     * @param phone
     * @return
     */
    private User createNewUser(String phone) {
        // 创建新用户并进行初始化
        User user = new User();
        user.setPhone(phone);
        user.setNickName(USER_NICK_NAME_PREFIX + RandomUtil.randomNumbers(10));
        // 保存用户到数据库中
        save(user);
        // 返回用户
        return user;
    }

    /**
     * 实现登出功能
     * @return
     */
    @Override
    public Result logout() {
        // 首先获取当前线程绑定的请求上下文，然后将其强转为HTTP请求特用的ServletRequestAttributes，然后拿到请求体，获取其中的session
        HttpSession session = ((ServletRequestAttributes) RequestContextHolder.
                currentRequestAttributes()).getRequest().getSession(false);
        if(session != null){
            session.invalidate();
        }else{
            return Result.fail("登录状态异常！");
        }
        UserHolder.removeUser();
        return Result.ok("用户已退出登录状态！");
    }
}
